package model;

/**
 * A class to represent a distinct Timestamp, holding a date and a time
 * (in seconds).
 * @author Stephen Hunt and Niel Lebeck
 *
 */
public class Time {
    private static final int DAYS_IN_MONTH = 31;
    private static final int DAYS_IN_YEAR = 366;
    private static final int HOURS_IN_PERIOD = 12;
    private static final int MINUTES_IN_DAY = 1440;
    private static final int SECONDS_IN_MINUTE = 60;
    private static final int INPUT_FIELDS = 3;

    private int myDate;
    private int myTime;

    /**
     * Constructor.
     */
    public Time() {
        myDate = 0;
        myTime = 0;
    }

    /**
     * @param d date
     * @param t time
     */
    public Time(int d, int t) {
        myDate = d;
        myTime = t;
    }

    /**
     * @param timestamp string
     * @throws WebHistoryDataException if time is formatted improperly.
     */
    public Time(String timestamp) throws WebHistoryDataException {
        String[] splitString = timestamp.split(" ");
        String[] splitDate = splitString[0].split("/");
        String[] splitTime = splitString[1].split(":");
        String dayPeriod = splitString[2];
        if (splitString.length < INPUT_FIELDS ||
                splitDate.length < INPUT_FIELDS ||
                splitTime.length < INPUT_FIELDS) {
            throw new WebHistoryDataException("improperly formatted timestamp: " +
                    "timestamp");
        }
        myDate = Integer.parseInt(splitDate[0]) * DAYS_IN_MONTH +
                Integer.parseInt(splitDate[1]) +
                Integer.parseInt(splitDate[2]) * DAYS_IN_YEAR;
        myTime = Integer.parseInt(splitTime[0]) * MINUTES_IN_DAY +
                Integer.parseInt(splitTime[1]) * SECONDS_IN_MINUTE +
                Integer.parseInt(splitTime[2]);
        if ("PM".equals(dayPeriod)) {
            myTime += MINUTES_IN_DAY * HOURS_IN_PERIOD;
        }
        if ("12".equals(splitTime[0])) {
            myTime -= MINUTES_IN_DAY * HOURS_IN_PERIOD;
        }
    }

    /**
     * Get the date of this Time object.
     * @return the Date of this object
     */
    public int getDate() {
        return myDate;
    }

    /**
     * Get the time of this Time object.
     * @return the time of this object
     */
    public int getTime() {
        return myTime;
    }

    /**
     * Determine if the Time represented by this object is after
     * that represented by another object.
     * @param otherTime the Time object being compared to
     * @return true if this Time is later than the other.
     */
    public boolean isAfter(Time otherTime) {
        if (otherTime.getDate() > myDate) {
            return true;
        }
        if (otherTime.getDate() < myDate) {
            return false;
        }
        if (otherTime.getTime() > myTime) {
            return true;
        }
        return false;
    }

    /**
     * Get a Time object representing the difference between this
     * Time and another Time.
     * @param otherTime the Time object being compared to
     * @return Time representing the difference between the two Times
     */
    public Time getDiff(Time otherTime) {
        return new Time(Math.abs(myDate - otherTime.getDate()),
                Math.abs(myTime - otherTime.getTime()));
    }

    /**
     * Add another Time object to this object.
     * @param otherTime the Time object being added to this one
     */
    public void add(Time otherTime) {
        myTime += otherTime.getTime();
        myDate += otherTime.getDate();
    }
}
